<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			#mycanvas {
				border: 1px solid black;
				margin: 50px auto;
				display: block;
			}
		</style>
	</head>
	<body>
		<canvas id="mycanvas" width="288" height="512"></canvas>
	</body>
	<script type="text/javascript">
		var mycanvas = document.getElementById("mycanvas");
		var context = mycanvas.getContext("2d");

		var imgPathArr = [{
				name: "bg_day",
				path: "images/bg_day.png"
			},
			{
				name: "bird0_0",
				path: "images/bird0_0.png"
			},
			{
				name: "bird0_1",
				path: "images/bird0_1.png"
			},
			{
				name: "bird0_2",
				path: "images/bird0_2.png"
			},
			{
				name: "button_play",
				path: "images/button_play.png"
			},
			{
				name: "font_048",
				path: "images/font_048.png"
			},
			{
				name: "font_049",
				path: "images/font_049.png"
			},
			{
				name: "font_050",
				path: "images/font_050.png"
			},
			{
				name: "font_051",
				path: "images/font_051.png"
			},
			{
				name: "font_052",
				path: "images/font_052.png"
			},
			{
				name: "font_053",
				path: "images/font_053.png"
			},
			{
				name: "font_054",
				path: "images/font_054.png"
			},
			{
				name: "font_055",
				path: "images/font_055.png"
			},
			{
				name: "font_056",
				path: "images/font_056.png"
			},
			{
				name: "font_057",
				path: "images/font_057.png"
			},
			{
				name: "land",
				path: "images/land.png"
			},
			{
				name: "pipe_down",
				path: "images/pipe_down.png"
			},
			{
				name: "pipe_up",
				path: "images/pipe_up.png"
			},
			{
				name: "text_game_over",
				path: "images/text_game_over.png"
			},
			{
				name: "title",
				path: "images/title.png"
			},
			{
				name: "tutorial",
				path: "images/tutorial.png"
			},
			{
				name: "simple",
				path: "images/简单模式.png"
			},
			{
				name: "difficulty",
				path: "images/困难模式.png"
			},
			{
				name: "nightmare",
				path: "images/噩梦模式.png"
			}
		];
		var imgsObj = {}; //定义一个空对象用来保存图片的路径
		var count = imgPathArr.length; //讲整个数据内容的长度保存到一个变量中
		imgPathArr.forEach(function(obj) { //循环整个数据
			var img = new Image(); //创建一个新的img标签
			img.src = obj.path; //依次拿出数据中的图片地址
			imgsObj[obj.name] = img; //依次创建出来所有的img标签
			img.onload = function() { //预加载事件
				count--; //数量依次减少
				if (count == 0) { //如果数量减少到0说明全部加载完成
					game(imgsObj); //将其作为形参传入game函数中
				}
			}
		});

		function game(data) {
			//绘制游戏首页面
			//场景1
			//定义场景变量
			var scene = 1;
			//定义场景1相关变量
			//标题动画y坐标
			var titleY = 0;
			//闪烁图片相关变量
			//透明度
			var alpha = 1;
			//透明度变化速度
			var alphaSpeed = -0.1;

			//定义场景2场景4场景5的通用相关变量
			var bgX = 0; //这里定义的是背景的宽度
			var pipeX = 300; //这里定义的是管道之间距离的宽度
			//开口140
			// max = 400-140-30=230,min=30
			//向下管道随机高度
			var pipeDown = parseInt(Math.random() * 200 + 30);
			//向上管道高度计算
			var pipeUp = 400 - 140 - pipeDown;
			//小鸟初始位置坐标
			var birdX = 50;
			var birdY = 100;
			//小鸟是否为下降状态
			var isDown = true; //true是下降状态，false是上升状态
			//小鸟上升或者下降的加速度
			var birdF = 0;
			//小鸟上升或者下降时的旋转角度
			var birdAlpha = 0;
			//得分
			var score = 0;
			//是否加分的标志变量
			var addScoreflag = true;
			var timer = setInterval(function() {
				context.clearRect(0, 0, 288, 512); //清楚整个画布
				if (scene == 1) { //当进入场景1时
					//1.1绘制背景图
					context.drawImage(data.bg_day, 0, 0);
					//1.2绘制标题动画
					titleY += 5; //这里相当于标题图的移动速度
					if (titleY >= 126) { //判断是否大于126
						titleY = 126; //如果大于等于126就停留在此处
					}
					context.drawImage(data.title, 55, titleY); //这里将标题的图片绘制出来坐标就是前面算的titleY
					//1.3绘制闪烁图片
					alpha += alphaSpeed; //将右边的值赋给左边
					if (alpha < 0.3) { //如果alpha小于0.3
						alphaSpeed = 0.1 //alphaSpeed就为0.1，由于定时器的原因会不断执行
					}
					if (alpha >= 1) { //如果alpha大于等于1
						alphaSpeed = -0.1 //alphaSpeed就为-0.1，由于定时器的原因会不断执行
					}
					context.save(); //保存当前context所有设置，不是画面
					context.globalAlpha = alpha; //将alpha的值赋给全局的阿尔法值
					context.drawImage(data.tutorial, 85, 215); //这里是需要闪烁的图片
					context.restore(); //恢复保存的所有设置
					//1.4绘制游戏按钮
					context.drawImage(data.button_play, 0, 0, 116, 70, 86, 300, 116, 70); //这是开始按钮
					context.drawImage(data.simple, 0, 0, 102, 50, 93, 360, 102, 50); //简单模式
					context.drawImage(data.difficulty, 0, 0, 102, 50, 93, 410, 102, 50); //困难模式
					context.drawImage(data.nightmare, 0, 0, 102, 50, 93, 460, 102, 50); //噩梦模式
					function show() { //相同代码写入函数直接调用
						//开口140
						// max = 400-140-30=230,min=30
						//向下管道随机高度
						pipeDown = parseInt(Math.random() * 200 + 30);
						//向上管道高度计算
						pipeUp = 400 - 140 - pipeDown;
						//小鸟初始位置坐标
						birdX = 50;
						birdY = 100;
						//小鸟是否为下降状态
						isDown = true; //true是下降状态，false是上升状态
						//小鸟上升或者下降的加速度
						birdF = 0;
						//小鸟上升或者下降时的旋转角度
						birdAlpha = 0;
						//得分
						score = 0;
						//是否加分的标志变量
						addScoreflag = true;
					}
					//1.5给按钮添加单击事件，
					// 实际上是添加到canvas元素上，但指定单击区域进行响应
					mycanvas.onclick = function(ev) {
						//获取鼠标单击位置
						//判断单击位置是否在按钮图片上
						// 如果在按钮图片上则执行对应相应的代码，转场景2，让scene=2、
						//这里由于位置关系已经写在简单模式上面了
						//1.5.1、获取鼠标点击位置坐标
						var x = ev.offsetX;
						var y = ev.offsetY;
						//console.log(x, y);
						//1.5.2、计算按钮图片左上角坐标x1和y1及右下角坐标x2，y2
						//x1和y1就是图片放置在canvas中时指定的坐标
						var x1 = 93;
						var y1 = 360;
						//x2和y2
						var x2 = 93 + 102;
						var y2 = 360 + 53;
						//当单击位置在按钮图片所在区域时，切换场景
						if ((x > x1 && x < x2) && (y > y1 && y < y2)) {
							scene = 2; //进入场景2
							//对场景2的变量进行重置
							bgX = 0;
							pipeX = 300;
						}
						show();
						//获取鼠标单击位置
						//判断单击位置是否在按钮图片上
						// 如果在按钮图片上则执行对应相应的代码，转场景4，让scene=4
						//1.5.1、获取鼠标点击位置坐标
						var x = ev.offsetX;
						var y = ev.offsetY;
						//console.log(x, y);
						//1.5.2、计算按钮图片左上角坐标x1和y1及右下角坐标x2，y2
						//x1和y1就是图片放置在canvas中时指定的坐标
						var x1 = 93;
						var y1 = 410;
						//x2和y2
						var x2 = 93 + 102;
						var y2 = 410 + 53;
						//当单击位置在按钮图片所在区域时，切换场景
						if ((x > x1 && x < x2) && (y > y1 && y < y2)) {
							scene = 4; //进入场景2
							//对场景2的变量进行重置
							bgX = 0;
							pipeX = 300;
						}
						show();
						//获取鼠标单击位置
						//判断单击位置是否在按钮图片上
						// 如果在按钮图片上则执行对应相应的代码，转场景5，让scene=5
						//这里是噩梦难度
						//1.5.1、获取鼠标点击位置坐标
						var x = ev.offsetX;
						var y = ev.offsetY;
						//console.log(x, y);
						//1.5.2、计算按钮图片左上角坐标x1和y1及右下角坐标x2，y2
						//x1和y1就是图片放置在canvas中时指定的坐标
						var x1 = 93;
						var y1 = 460;
						//x2和y2
						var x2 = 93 + 102;
						var y2 = 460 + 53;
						//当单击位置在按钮图片所在区域时，切换场景
						if ((x > x1 && x < x2) && (y > y1 && y < y2)) {
							scene = 5; //进入场景2
							//对场景2的变量进行重置
							bgX = 0;
							pipeX = 300;

						}
						show();
					}
				} else if (scene == 2) {
					//2.1绘制运动背景（天空和地面），计算动态坐标
					bgX -= 1; //这里是图片左移的速度
					if (bgX <= -288) {
						bgX = 0;
					}
					//2.2绘制天空和地面及其缺失部分
					//绘制天空及缺失的部分
					context.drawImage(data.bg_day, bgX, 0);
					context.drawImage(data.bg_day, 288 + bgX, 0);
					//绘制地面及缺失的部分
					context.drawImage(data.land, bgX, 400);
					context.drawImage(data.land, 288 + bgX, 400);
					//2.3绘制管道
					//计算管道的动态坐标
					pipeX -= 1; //管道移动的速度由于是简单模式所以比较慢
					if (pipeX <= -55) {
						pipeX = 300;
						pipeDown = parseFloat(Math.random() * 200 + 30);
						pipeUp = 400 - 140 - pipeDown;
						addScoreflag = true; //得分标志变量改变，通过后允许加分
					}
					socer(); //调用相同代码
				} else if (scene == 4) {
					//在这里绘制困难模式的代码。
					//2.1绘制运动背景（天空和地面），计算动态坐标
					bgX -= 3; //困难模式的速度
					if (bgX <= -288) {
						bgX = 0;
					}
					//2.2绘制天空和地面及其缺失部分
					//绘制天空及缺失的部分
					context.drawImage(data.bg_day, bgX, 0);
					context.drawImage(data.bg_day, 288 + bgX, 0);
					//绘制地面及缺失的部分
					context.drawImage(data.land, bgX, 400);
					context.drawImage(data.land, 288 + bgX, 400);
					//2.3绘制管道
					//计算管道的动态坐标
					pipeX -= 3; //困难模式的速度
					if (pipeX <= -55) {
						pipeX = 300;
						pipeDown = parseFloat(Math.random() * 200 + 30);
						pipeUp = 400 - 140 - pipeDown;
						addScoreflag = true; //得分标志变量改变，通过后允许加分
					}
					socer(); //调用相同代码
				} else if (scene == 5) {
					//在这里绘制噩梦模式的代码。
					//2.1绘制运动背景（天空和地面），计算动态坐标
					bgX -= 6; //噩梦模式的速度
					if (bgX <= -288) {
						bgX = 0;
					}
					//2.2绘制天空和地面及其缺失部分
					//绘制天空及缺失的部分
					context.drawImage(data.bg_day, bgX, 0);
					context.drawImage(data.bg_day, 288 + bgX, 0);
					//绘制地面及缺失的部分
					context.drawImage(data.land, bgX, 400);
					context.drawImage(data.land, 288 + bgX, 400);
					//2.3绘制管道
					//计算管道的动态坐标
					pipeX -= 6; //噩梦模式的速度
					if (pipeX <= -55) {
						pipeX = 300;
						pipeDown = parseFloat(Math.random() * 200 + 30);
						pipeUp = 400 - 140 - pipeDown;
						addScoreflag = true; //得分标志变量改变，通过后允许加分
					}
					socer();
				} else if (scene == 3) {
					//把场景2最后面画面显示出来
					context.drawImage(data.bg_day, 0, 0);
					context.drawImage(data.land, 0, 400);
					//绘制管道
					context.drawImage(data.pipe_down, 0, 320 - pipeDown, 52, pipeDown, pipeX, 0, 52, pipeDown);
					context.drawImage(data.pipe_up, 0, 0, 52, pipeUp, pipeX, pipeDown + 140, 52, pipeUp);
					birdY += 5;
					if (birdY >= 400 - 48 + 16) {
						birdY = 400 - 48 + 16
					}
					context.drawImage(data.bird0_0, birdX, birdY);
					//gameover图片文字显示
					context.drawImage(data.text_game_over, 40, 100);
					context.font = "30px 黑体";
					context.fillStyle = "white";
					context.fillText("你得了" + score + "分", 60, 200);
					context.fillText("点击任意位置", 40, 300);
					context.fillText("重新开始游戏", 40, 350);
					//点击任意位置,重新开始游戏
					mycanvas.onclick = function() {
						scene = 1;
						//对场景1相关变量重置
						titleY = 0;
					}
				}
			}, 20)

			function socer() {
				//2.4绘制管道
				context.drawImage(data.pipe_down, 0, 320 - pipeDown, 52, pipeDown, pipeX, 0, 52, pipeDown);
				context.drawImage(data.pipe_up, 0, 0, 52, pipeUp, pipeX, pipeDown + 140, 52, pipeUp);

				//2.5绘制小鸟//不用此功能了
				// context.drawImage(data.bird0_0,birdX,birdY);

				//2.6小鸟下降和上升状态时对应的加速度，坐标和旋转角度计算
				if (isDown) { //下降状态
					//下降速度一：无加速度
					// birdY++;//匀速下降，不符合物理现象
					//下降速度二：有加速度
					birdF++;
					// birdY += birdF;//有加速度，但是下降太快1
					birdY += birdF / 6; //适中2
					// birdY += Math.pow(birdF,2)/60;////有加速度，但是下降太快3
					birdAlpha = birdF / 18;
				} else { //上升状态
					//上升速度一：无加速度
					// birdY--;//匀速上升，不符合物理现象
					//上升速度二：有加速度
					birdF++;
					// birdY -= birdF;//上升太快
					// birdY -= Math.pow(25-birdF,2)/60;////有加速度，但是下降太快
					birdY -= (25 - birdF) / 6; //适中
					birdAlpha = -(25 - birdF) / 18;
					if (birdF >= 25) {
						isDown = true;
						birdF = 0;
					}
				}
				//2.11显示得分
				// score = 125;
				var scoreStr = score.toString(); //"125"
				for (var i = 0; i < scoreStr.length; i++) {
					var numChar = scoreStr[i];
					var key = "font_0" + (48 + parseInt(numChar));
					context.drawImage(data[key], 60 + i * 16, 100);
				}
				//2.7小鸟旋转
				// context.rotate(birdAlpha);//不能直接旋转画布
				// 先保存画布相关参数
				context.save();
				//再设置新参数
				//1、把旋转中心点坐标设置为小鸟图片中心
				context.translate(birdX + 24, birdY + 24);
				context.rotate(birdAlpha);
				//绘制新图片
				context.drawImage(data.bird0_0, -24, -24); //绘制小鸟
				//最后恢复参数
				context.restore();
				//2.8单击任意位置，小鸟上升
				mycanvas.onclick = function() {
					//改变小鸟为上升状态
					isDown = false;
					birdF = 0;
				}
				//2.9小鸟死亡，gameover
				//有三种方式死亡
				//方式一：撞地面
				if (birdY >= 400 - 48) {
					console.log("方式一死亡");
					scene = 3;
				}
				//方式二：撞天空
				if (birdY <= 0) {
					console.log("方式二：撞天空");
					scene = 3;
				}
				//方式三：撞管道
				//在管道的区域内，才有可能撞管道
				if (birdX + 48 >= pipeX && birdX <= pipeX + 52) {
					//如果不在开口内
					//撞上面管道
					if (birdY <= pipeDown) {
						console.log(pipeDown)
						console.log("方式三：撞上面管道");
						scene = 3;
					}
					//撞下面管道
					if (birdY + 48 >= pipeDown + 140) {
						console.log("方式三：撞下面管道");
						scene = 3;
					}
				}
				//2.10通过管道，得分
				if (birdX >= pipeX + 52 && addScoreflag) {
					score++;
					//得分之后，标志变量状态改变
					addScoreflag = false;
					console.log(score + "分");
				}
			}
		}
	</script>
</html>
